#include "lecteur_scenario.hpp"
#include "echapper.hpp"
#include "protocole.hpp"
#include <iostream>

#define NOM_CLASSE "LecteurScenario"

#include "deboguer.hpp"

Evenement::Evenement(Type type,
		     const Protocole::Message & message):
  m_type(type), m_message(message)
{
}
Evenement::Evenement(const QStringList & phrase):
m_type(Evenement::parser_phrase(phrase).m_type),
m_message(Evenement::parser_phrase(phrase).m_message)
{
}
Evenement::Evenement(const Evenement & e):
  m_type(e.type()), m_message(e.message())
{
}
Evenement::Type Evenement::type() const
{
  return m_type;
}
Protocole::Message Evenement::message() const
{
  return Protocole::Message(m_message);
}
Evenement Evenement::ClientDit(const Protocole::Message & message)
{
  return Evenement(Evenement::CLIENT_DIT, message);
}
Evenement Evenement::ServeurDit(const Protocole::Message & message)
{
  return Evenement(Evenement::SERVEUR_DIT, message);
}
Evenement Evenement::parser_phrase(const QStringList & phrase)
{
  Protocole::Message m;
  m.compris = true;
  //On complète le message.
  //C'est très confortable : on sait que les spécifications de
  //rassembler() sont respectées. 
  if(phrase[0] == "identifier")
    {
      m.type = Protocole::IDENTIFIER;
      QByteArray nom_donne = phrase[1].toUtf8();
      for(int i = 0 ; i < TAILLE_NOM ; i++)
	{
	  if(i < nom_donne.size())
	    {
	      m.m.identifier.nom[i] = nom_donne[i];
	    }
	  else
	    {
	      m.m.identifier.nom[i] = '\0';
	    }
	}
    }
  else if(phrase[0] == "inviter")
    {
      m.type = Protocole::INVITER;
      for(int i = 0 ; i < 4 ; i++)
	{
	  QByteArray nom_donne = phrase[i + 1].toUtf8();
	  for(int j = 0 ; j < TAILLE_NOM ; j++)
	    {
	      if(j < nom_donne.size())
		{
		  m.m.inviter.noms[i][j] = nom_donne[j];
		}
	      else
		{
		  m.m.inviter.noms[i][j] = '\0';
		}
	    }
	}
    }
  else if(phrase[0] == "priser")
    {
      m.type = Protocole::PRISE;
      m.m.prise.niveau = phrase[1].toInt();
    }
  else if(phrase[0] == "appeler")
    {
      m.type = Protocole::APPELER;
      m.m.appeler.carte = phrase[1].toInt();
    }
  else if(phrase[0] == "ecarter")
    {
      m.type = Protocole::ECART;
      for(int i = 0 ; i < 3 ; i++)
	{
	  m.m.ecart.ecart[i] = phrase[i + 1].toInt();
	}
    }
  else if(phrase[0] == "jouer")
    {
      m.type = Protocole::REQUETE;
      m.m.requete.carte = phrase[1].toInt();
    }
  else if(phrase[0] == "erreur_protocole")
    {
      m.type = Protocole::ERREUR_PROTOCOLE;
    }
  else if(phrase[0] == "refuse")
    {
      m.type = Protocole::REFUSE;
    }
  else if(phrase[0] == "entree")
    {
      m.type = Protocole::ENTREE;
      QByteArray nom_donne = phrase[1].toUtf8();
      for(int i = 0 ; i < TAILLE_NOM ; i++)
	{
	  if(i < nom_donne.size())
	    {
	      m.m.entree.nom[i] = nom_donne[i];
	    }
	  else
	    {
	      m.m.entree.nom[i] = '\0';
	    }
	}
    }
  else if(phrase[0] == "sortie")
    {
      m.type = Protocole::SORTIE;
      QByteArray nom_donne = phrase[1].toUtf8();
      for(int i = 0 ; i < TAILLE_NOM ; i++)
	{
	  if(i < nom_donne.size())
	    {
	      m.m.sortie.nom[i] = nom_donne[i];
	    }
	  else
	    {
	      m.m.sortie.nom[i] = '\0';
	    }
	}
    }
  else if(phrase[0] == "noms")
    {
      m.type = Protocole::NOMS;
      for(int i = 0 ; i < 5 ; i++)
	{
	  QByteArray nom_donne = phrase[i + 1].toUtf8();
	  for(int j = 0 ; j < TAILLE_NOM ; j++)
	    {
	      if(j < nom_donne.size())
		{
		  m.m.noms.noms[i][j] = nom_donne[j];
		}
	      else
		{
		  m.m.noms.noms[i][j] = '\0';
		}
	    }
	}
    }
  else if(phrase[0] == "numero")
    {
      m.type = Protocole::NUMERO;
      m.m.numero.n = phrase[1].toInt();
    }
  else if(phrase[0] == "distribution")
    {
      m.type = Protocole::DISTRIBUTION;
      for(int i = 0 ; i < 15 ; i++)
	{
	  m.m.distribution.cartes[i] = phrase[i + 1].toInt();
	}
    }
  else if(phrase[0] == "contrat")
    {
      m.type = Protocole::CONTRAT;
      m.m.contrat.niveau = phrase[1].toInt();
    }
  else if(phrase[0] == "appel")
    {
      m.type = Protocole::APPEL;
    }
  else if(phrase[0] == "contrat_final")
    {
      m.type = Protocole::CONTRAT_FINAL;
      m.m.contrat_final.preneur = phrase[1].toInt();
      m.m.contrat_final.niveau = phrase[2].toInt();
      m.m.contrat_final.appel = phrase[3].toInt();
    }
  else if(phrase[0] == "chien")
    {
      m.type = Protocole::CHIEN;
      for(int i = 0 ; i < 3 ; i++)
	{
	  m.m.chien.chien[i] = phrase[i + 1].toInt();
	}
    }
  else if(phrase[0] == "atout")
    {
      m.type = Protocole::ATOUT;
      for(int i = 0 ; i < 3 && i + 1 < phrase.size() ; i++)
	{
	  m.m.atout.cartes[i] = phrase[i + 1].toInt();
	}
      m.m.atout.nombre = 3;
      if(phrase.size() <= 4)
	{
	  m.m.atout.nombre = phrase.size() - 1;
	}
    }
  else if(phrase[0] == "jeu")
    {
      m.type = Protocole::JEU;
      m.m.jeu.ouvreur = 0;
    }
  else if(phrase[0] == "carte")
    {
      m.type = Protocole::CARTE;
      m.m.carte.carte = phrase[1].toInt();
    }
  else if(phrase[0] == "pli")
    {
      m.type = Protocole::PLI;
      m.m.pli.joueur = phrase[1].toInt();
    }
  else if(phrase[0] == "resultat")
    {
      m.type = Protocole::RESULTAT;
      for(int i = 0 ; i < 5 ; i++)
	{
	  m.m.resultat.resultats[i] = phrase[i + 1].toInt();
	}
    }
  else
    {
      std::cerr<<"ERREUR : "<<phrase[0].toUtf8().data()<<std::endl;
    }
  //On déduit le type.
  Evenement::Type t;
  switch(m.type)
    {
    case Protocole::PRISE:
    case Protocole::APPELER:
    case Protocole::ECART:
    case Protocole::MONTRER_POIGNEE:
    case Protocole::REQUETE:
    case Protocole::IDENTIFIER:
    case Protocole::INVITER:
      t = Evenement::CLIENT_DIT;
      break;
    default:
      t = Evenement::SERVEUR_DIT;
    }
  return Evenement(t, m);
}

LecteurScenario::LecteurScenario(QObject * parent):
  QObject(parent)
{
  ENTER("LecteurScenario(QObject * parent)");
  ADD_ARG("parent", parent);
}

void LecteurScenario::lire_scenario(const QString & contenu_fichier,
				    QStringList & ignored)
{
  ENTER("lire_scenario(const QString & contenu_fichier, QStringList & ignored)");
  ADD_ARG("contenu_fichier.toUtf8().data()", contenu_fichier.toUtf8().data());
  QStringList mots = decouper(contenu_fichier);
  QVector<QStringList> ev = rassembler(mots, ignored);
  scenario.clear();
  for(QVector<QStringList>::const_iterator i = ev.begin() ;
      i != ev.end() ; i++)
    {
      scenario.append(QSharedPointer<Evenement>(new Evenement(*i)));
    }
  avancer();
}

void LecteurScenario::avancer()
{
  ENTER("avancer()");
  if(!scenario.isEmpty())
    switch(scenario.front()->type())
      {
      case Evenement::CLIENT_DIT:
	//On peut continuer si repliques_client n'est pas vide
	if(repliques_client.isEmpty())
	  {
	    //On attend le slot recevoirMessage()
	  }
	else
	  {
	    Protocole::Message m = repliques_client.takeFirst();
	    if(Protocole::meme_message(m, scenario.first()->message()))
	      {
		//On avance
		scenario.pop_front();
		avancer();
	      }
	    else
	      {
		emit erreur(m, scenario.first()->message());
		scenario.clear();
	      }
	  }
	break;
      case Evenement::SERVEUR_DIT:
	emit doit_emettre(scenario.takeFirst()->message());
	avancer();
	break;
      default: //Impossible.
	break;
    }
  else while(!repliques_client.isEmpty())
	 {
	   emit hors_scenario(repliques_client.takeFirst());
	 }
}

void LecteurScenario::recevoir_message(Protocole::Message m)
{
  ENTER("recevoir_message(Protocole::Message m)");
  ADD_ARG("m", m);
  repliques_client.append(m);
  avancer();
}
